﻿# ---------------------------------------------------- #
# Windows Server Failover Cluster (WSFC) Configuration #
# ---------------------------------------------------- #
param([string]$virtualMachineService, [string]$virtualMachineName)

# Return resource owners list
function Get-ResourceOwners($owners)
{
	$result = @();
	foreach ($owner in $owners.owner)
	{
		$result += $owner.name
	}
	return $result
}

Write-Information "Virtual machine '$virtualMachineName' executing Windows Server Failover Cluster '$($script.type)' configuration ... " -NoNewLine $true
$userName = $subscription.virtualMachines.adminUserName
$password = $subscription.virtualMachines.password
$netBiosDomain = $subscription.virtualMachines.netBiosDomain
$uri = Get-AzureWinRMUri -ServiceName $virtualMachineService -Name $virtualMachineName
$credential = New-Object System.Management.Automation.PSCredential(($netBiosDomain + "\" + $userName), (ConvertTo-SecureString $password -AsPlainText -Force))
$port = Get-VirtualMachineInstanceEndpointPort $subscription $virtualMachineName
$session = New-PSSession -ComputerName $uri[0].DnsSafeHost -Credential $credential -Port $port -UseSSL -Authentication Credssp
switch ($script.type)
{
	"Prepare"
	{
		Invoke-Command -Session $session -ScriptBlock {
			Add-WindowsFeature Failover-Clustering,RSAT-Clustering -WarningAction Ignore | Out-Null
		}
	}
	"Create"
	{
        if ($script.name.Length -gt 15) { throw "Cluster name '$($script.name)' length cannot exceed 15 characters." }
		Invoke-Command -Session $session -ScriptBlock {
	        param([string]$name, [string]$ipAddress)
            Import-Module FailoverClusters -WarningAction Ignore
            # Remove existing cluster
            if ((Get-Cluster -ErrorAction SilentlyContinue -WarningAction Ignore) -ne $null) { Get-Cluster | Remove-Cluster -CleanupAD -Force }
            # Create new cluster
            New-Cluster -Name $name -Node $Env:COMPUTERNAME –StaticAddress $ipAddress -NoStorage -Force | Out-Null
            # Verify cluster configuration
            if ((Get-ClusterNode -ErrorAction SilentlyContinue).Name -ne $Env:COMPUTERNAME) { throw "Windows Server Failover Cluster configuration failed. Check 'C:\Windows\cluster\Reports\Create Cluster Wizard *.mht' for more details." }
		} -ArgumentList $script.name, $script.ipAddress
	}
	"Join"
	{
		Invoke-Command -Session $session -ScriptBlock {
	        param([string]$server)
            Import-Module FailoverClusters -WarningAction Ignore
            Add-ClusterNode -Name $server -WarningAction Ignore | Out-Null
		} -ArgumentList $script.name
	}
	"Set Witness"
	{
		Invoke-Command -Session $session -ScriptBlock {
			param([string]$fileShare)
			Set-ClusterQuorum -FileShareWitness $fileShare | Out-Null
		} -ArgumentList $script.fileShare
	}
	"Add IP"
	{
		Invoke-Command -Session $session -ScriptBlock {
	        param([string]$group, [string]$resource, [string]$networkAddress, [string]$ipAddress, [string]$probePort)
            Import-Module FailoverClusters -WarningAction Ignore
            $network = Get-ClusterNetwork | ? {$_.Address -eq $networkAddress}
            Add-ClusterResource -Name "IP Address $ipAddress" -Group $group -ResourceType "IP Address" | Set-ClusterParameter -Multiple @{"Address"="$ipAddress"; "ProbePort"="$probePort"; "SubnetMask"="$($network.AddressMask)"; "Network"="$($network.Name)"; "OverrideAddressMatch"=1; "EnableDhcp"="0"} | Out-Null
            Stop-ClusterResource -Name $resource | Out-Null
            $dependency = (Get-ClusterResourceDependency -Resource $resource).DependencyExpression
            $dependency = $dependency.Substring(1, $dependency.Length - 2)
            Set-ClusterResourceDependency -Resource $resource -Dependency "$dependency or [IP Address $ipAddress]" | Out-Null
            #Start-ClusterResource -Name $resource | Out-Null
            Start-ClusterResource -Name $group | Out-Null
		} -ArgumentList $script.group, $script.resource, $script.networkAddress, $script.ipAddress, $script.probePort
	}
	"Set Owners"
	{
		Invoke-Command -Session $session -ScriptBlock {
			param([string]$resource, [string[]]$owners)
			Get-ClusterResource -Name $resource | Set-ClusterOwnerNode -Owners $owners
		} -ArgumentList $script.resource, (Get-ResourceOwners $script.owners)
	}
	"Set Vote"
	{
		Invoke-Command -Session $session -ScriptBlock {
			param([string]$node, [string]$enabled)
            if ($enabled -eq $true)
            {
			    (Get-ClusterNode -Name $node).NodeWeight = 1
            }
            else
            {
			    (Get-ClusterNode -Name $node).NodeWeight = 0
            }
		} -ArgumentList $script.node, $script.enabled
	}
	default
	{
		throw "Windows Server Failover Cluster type '$($script.type)' is not supported."
	}
}
Remove-PSSession $session
Write-Text "done."